//-------------------------------------------------------------------------------------------------
// <copyright file="StyleFix.cs" company="OfficeClip LLC">
// Copyright (c) OfficeClip LLC.  All rights reserved.
// </copyright>
//-------------------------------------------------------------------------------------------------

namespace OfficeClip.OpenSource.StyleFix
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Text.RegularExpressions;

    /// <summary>
    /// A class to fix the styles
    /// </summary>
    public class StyleFix
    {
        private readonly string localFileContent;
        private readonly List<SAObject> localStyleCopObjects;
        private readonly string localFileName;

        private readonly List<string> outputFileLines;

        private static int CompareSAObjectByErrorId(SAObject x, SAObject y)
        {
            return x.ErrorId.CompareTo(y.ErrorId);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="StyleFix"/> class.
        /// </summary>
        /// <param name="fileContent">Content of the file.</param>
        /// <param name="styleCopObjects">The sa objects.</param>
        /// <param name="fileName">Name of the file.</param>
        public StyleFix(string fileContent, List<SAObject> styleCopObjects, string fileName)
        {
            this.localFileContent = fileContent;
            this.localStyleCopObjects = styleCopObjects;

            this.localFileName = Path.GetFileName(fileName);

            StringReader sr = new StringReader(this.localFileContent);
            string input;

            // Now go through each of the lines, look into the SAObject and copy stuff in the output lines
            this.outputFileLines = new List<string>();
            int lineNumber = 0;
            bool skipNextLine = false;
            bool skipThisLine = false;
			bool skipNextBlankLine = false;
            while ((input = sr.ReadLine()) != null)
            {
                lineNumber++;
                if (skipNextLine)
                {
                    skipNextLine = false;
                    continue;
                }
				if (skipNextBlankLine && (input.Trim().Length == 0))
				{
					skipNextBlankLine = false;
					continue;
				}

                string line = input.TrimEnd();
                List<SAObject> matchingSaob = this.FindLineNumber(lineNumber);
                if (matchingSaob != null)
                {
                    foreach (SAObject saob in matchingSaob)
                    {
                        switch (saob.ErrorId)
                        {
                            case "SA1000":
                                line = line.Replace("switch(", "switch (");
                                break;
                            case "SA1001":
                                line = OpenSource.StyleFix.Drivers.SA1001.Run(line, saob);
                                break;
                            case "SA1003":
                                line = OpenSource.StyleFix.Drivers.SA1003.Run(line, saob);
                                break;
                            case "SA1005":
                                line = Regex.Replace(line, @"^(\s*)//(\S)", @"$1////$2", RegexOptions.None);
                                break;
                            case "SA1009":
								line = OpenSource.StyleFix.Drivers.SA1009.Run(line, saob);
								break;
                            case "SA1010":
                                line = OpenSource.StyleFix.Drivers.SA1010.Run(line, saob);
                                break;
                            case "SA1025":
                                line = OpenSource.StyleFix.Drivers.SA1025.Run(line, saob);
                                break;
                            case "SA1027":
                                line = line.Replace("\t", "    ");
                                break;
                            case "SA1101":
                                line = OpenSource.StyleFix.Drivers.SA1101.Run(line, saob);
                                break;
							case "SA1121":
								line = OpenSource.StyleFix.Drivers.SA1121.Run(line, saob);
								break;
							case "SA1122":
                                line = line.Replace(@"""""", @"string.Empty");
                                break;
                            case "SA1500":
                                line = OpenSource.StyleFix.Drivers.SA1500.Run(line);
                                break;
                            case "SA1501":
                                line = OpenSource.StyleFix.Drivers.SA1501.Run(line);
                                break;
							case "SA1505":
                                skipNextLine = true;
                                break;
							case "SA1506":
							case "SA1508":
								skipNextBlankLine = true;
								break;
								//this.outputFileLines.RemoveAt(this.outputFileLines.Count - 1);
								//break;
							case "SA1509":
							case "SA1510":
                                this.outputFileLines.RemoveAt(this.outputFileLines.Count - 1);
                                break;
                            case "SA1512":
                                skipNextLine = true;
                                break;
                            case "SA1513":
                                line = line + System.Environment.NewLine;
                                break;
							case "SA1515":
							case "SA1516":
                                line = System.Environment.NewLine + line;
                                break;
                        }
                    }
                }

                if (skipThisLine)
                {
                    skipThisLine = false;
                }
                else
                {
                    foreach (
                        string str in line.Split(new string[] { System.Environment.NewLine }, StringSplitOptions.None))
                    {
                        this.outputFileLines.Add(
                            (string.IsNullOrEmpty(str)) ? string.Empty : str);
                    }
                }
            }

            // Now do some post processing
            if (this.FindStyleWarning("SA1200").Count > 0)
            {
                OpenSource.StyleFix.Drivers.SA1200.Run(ref this.outputFileLines);
            }

            // Always do this at the end
            if (this.FindStyleWarning("SA1210").Count > 0)
            {
                OpenSource.StyleFix.Drivers.SA1210.Run(ref this.outputFileLines);
            }

            if (this.FindStyleWarning("SA1507").Count > 0)
            {
                OpenSource.StyleFix.Drivers.SA1507.Run(ref this.outputFileLines);
            }

            if (this.FindStyleWarning("SA1633").Count > 0)
            {
                OpenSource.StyleFix.Drivers.SA1633.Run(this.localFileName, ref this.outputFileLines);
            }

            sr.Close();
        }

        /// <summary>
        /// Outputs the content of the file.
        /// </summary>
        /// <returns>The output content</returns>
        public string OutputFileContent()
        {
            StringBuilder sb = new StringBuilder();
            foreach (string str in this.outputFileLines)
            {
                sb.Append(str);
                sb.Append(System.Environment.NewLine);
            }

            return sb.ToString();
        }

        private List<SAObject> FindStyleWarning(string styleCopString)
        {
            List<SAObject> lsao = this.localStyleCopObjects.FindAll(sao => sao.ErrorId == styleCopString);
            return lsao;
        }

        private List<SAObject> FindLineNumber(int lineNumber)
        {
            return this.localStyleCopObjects.FindAll(sao => sao.LineNumber == lineNumber);
        }
    }
}
